package com.ruoyi.common.utils.job

import com.ruoyi.common.constant.Constants
import com.ruoyi.common.constant.ScheduleConstants
import com.ruoyi.common.utils.ExceptionUtil
import com.ruoyi.common.utils.bean.BeanUtils
import com.ruoyi.common.utils.spring.SpringUtils
import com.ruoyi.project.monitor.domain.SysJob
import com.ruoyi.project.monitor.domain.SysJobLog
import com.ruoyi.project.monitor.service.ISysJobLogService
import org.apache.commons.lang3.StringUtils
import org.quartz.Job
import org.quartz.JobExecutionContext
import org.quartz.JobExecutionException
import org.slf4j.LoggerFactory
import java.util.*

/**
 * 抽象quartz调用
 *
 * @author ruoyi
 */
abstract class AbstractQuartzJob : Job {
    @Throws(JobExecutionException::class)
    override fun execute(context: JobExecutionContext) {
        val sysJob = SysJob()
        BeanUtils.copyBeanProp(sysJob, context.mergedJobDataMap[ScheduleConstants.TASK_PROPERTIES])
        try {
            before(context, sysJob)
            doExecute(context, sysJob)
            after(context, sysJob, null)
        } catch (e: Exception) {
            log.error("任务执行异常  - ：", e)
            after(context, sysJob, e)
        }
    }

    /**
     * 执行前
     *
     * @param context 工作执行上下文对象
     * @param sysJob 系统计划任务
     */
    protected fun before(context: JobExecutionContext?, sysJob: SysJob?) {
        threadLocal.set(Date())
    }

    /**
     * 执行后
     *
     * @param context 工作执行上下文对象
     * @param sysScheduleJob 系统计划任务
     */
    private fun after(context: JobExecutionContext?, sysJob: SysJob?, e: Exception?) {
        val startTime = threadLocal.get()
        threadLocal.remove()
        val sysJobLog = SysJobLog()
        sysJobLog.jobName = sysJob!!.jobName
        sysJobLog.jobGroup = sysJob.jobGroup
        sysJobLog.invokeTarget = sysJob.invokeTarget
        sysJobLog.startTime = startTime
        sysJobLog.stopTime = Date()
        val runMs = sysJobLog.stopTime!!.time - sysJobLog.startTime!!.time
        sysJobLog.jobMessage = sysJobLog.jobName + " 总共耗时：" + runMs + "毫秒"
        if (e != null) {
            sysJobLog.status = Constants.FAIL
            val errorMsg = StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 2000)
            sysJobLog.exceptionInfo = errorMsg
        } else {
            sysJobLog.status = Constants.SUCCESS
        }

        // 写入数据库当中
        SpringUtils.getBean(ISysJobLogService::class.java).addJobLog(sysJobLog)
    }

    /**
     * 执行方法，由子类重载
     *
     * @param context 工作执行上下文对象
     * @param sysJob 系统计划任务
     * @throws Exception 执行过程中的异常
     */
    @Throws(Exception::class)
    protected abstract fun doExecute(context: JobExecutionContext?, sysJob: SysJob)

    companion object {
        private val log = LoggerFactory.getLogger(AbstractQuartzJob::class.java)

        /**
         * 线程本地变量
         */
        private val threadLocal = ThreadLocal<Date>()
    }
}
